package com.atguigu.juc.juc20210301;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 1 synchronized系统的关键字，java.util.concurrent.locks.ReentrantLock后来的类
 * 2 锁的分类说明
 *   synchronized   可重入锁+ 非公平锁
 *   ReentrantLock  可重入锁+ 非公平锁/公平锁，默认是非公平锁  Re  entrant  Lock
 *
 * 3 ReentrantLock新特性，
 *   synchronized（ReentrantLock。lock）死心眼，抢不到锁不走，不离不弃，----不见不散，
 *
 *   ReentrantLock给我一定时间，等不到，我就走了。不死等
 *    lock
 *    tryLock
 *    tryLock(2L,TimeUnit.SECONDS)
 *
 */
class BusTicket
{
    private int number = 30;
    private ReentrantLock reentrantLock = new ReentrantLock();//默认是非公平锁

    public void sale()
    {
        /*reentrantLock.lock();
        try
        {
            if(number > 0)
            {
                System.out.println(Thread.currentThread().getName()+"\t卖出第: "+(number--)+"\t还剩下: "+number);
            }
        }finally {
            reentrantLock.unlock();
        }*/

        try
        {
            if(reentrantLock.tryLock(2L,TimeUnit.SECONDS))
            {
                if(number > 0)
                {
                    System.out.println(Thread.currentThread().getName()+"\t卖出第: "+(number--)+"\t还剩下: "+number);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(reentrantLock.isHeldByCurrentThread())
            {
                reentrantLock.unlock();
            }
        }
    }

}


/**
 * @auther zzyy
 * @create 2020-04-08 8:08
 */
public class ReentrantLockDemo
{
    public static void main(String[] args)
    {
        BusTicket busTicket = new BusTicket();

        new Thread(() -> {for (int i = 1; i <=33; i++) busTicket.sale();},"A").start();
        new Thread(() -> {for (int i = 1; i <=33; i++) busTicket.sale();},"B").start();
        new Thread(() -> {for (int i = 1; i <=33; i++) busTicket.sale();},"C").start();
    }
}









/*
1. ReentrantLock可以实现公平锁和非公平锁
2. ReentrantLock默认实现的是非公平锁
3. ReentrantLock的获取锁和释放锁必须成对出现，锁了几次，也要释放几次
4. 释放锁的操作必须放在ﬁnally中执行
5. 实例方法tryLock()获会尝试获取锁，会立即返回，返回值表示是否获取成功
6. 实例方法tryLock(long timeout, TimeUnit unit)会在指定的时间内尝试获取锁，
    指定的时间内是否能够获取锁，都会返回，返回值表示是否获取锁成功
* */
